{
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7-final"
  },
  "orig_nbformat": 2,
  "kernelspec": {
   "name": "python3",
   "display_name": "DataAnalysis"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2,
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tools import show_subtitle\n",
    "%matplotlib inline"
   ]
  },
  {
   "source": [
    "# Chap4 编写结构化的程序\n",
    "1.  怎样才能写出结构良好，可读性强的程序，从而方便重用？\n",
    "2.  基本的结构块，例如：循环、函数和赋值是如何执行的？\n",
    "3.  Python 编程的陷阱还有哪些，如何避免它们？"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "source": [
    "## 4.6 程序开发(P169)"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "source": [
    "### 4.6.1 Python 模块的结构(P170)\n",
    "-   每个py文件都需要有注释头，包括：模块标题 和 作者信息。\n",
    "-   模块级的 docstring，三重引号的多行字符串\n",
    "-   模块需要的所有导入语句，然后是所有全局变量，接着是组成模块主要部分的一系列函数的定义\n",
    "\n",
    "注：Python 3 不支持 __file__"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "source": [
    "### 4.6.2 多模块程序(P171)\n",
    "-   将工作分成几个模块\n",
    "-   使用 import 语句访问其他模块定义的函数\n",
    "-   保持各个模块的简单性，并且易于维护"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "source": [
    "### 4.6.3 误差源头(P173)"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "string=  ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n--------------- >find_words(string, 3)< ---------------\nresult=  []\n['dog', 'cat']\n--------------- >find_words(string, 2, ['ur'])< ---------------\nresult=  ['ur']\n['ur', 'so', 'to']\n--------------- >find_words(string, 3)< ---------------\nresult=  ['dog', 'cat']\n['dog', 'cat', 'dog', 'cat']\n--------------- >find_words(string, 2)< ---------------\nresult=  ['dog', 'cat', 'dog', 'cat']\n['dog', 'cat', 'dog', 'cat', 'so', 'to']\n--------------- >find_words(string, 2, ['ur'])< ---------------\nresult=  ['ur']\n['ur', 'so', 'to']\n--------------- >find_words(string, 3, ['ur'])< ---------------\nresult=  ['ur']\n['ur', 'dog', 'cat']\n"
     ]
    }
   ],
   "source": [
    "# 错误代码，result 只会被初始化一次\n",
    "def find_words(text, wordlength, result=[]):\n",
    "    \"\"\"寻找匹配 wordlength 长度的单词\"\"\"\n",
    "    print(\"result= \", result)\n",
    "    for word in text:\n",
    "        if len(word) == wordlength:\n",
    "            result.append(word)\n",
    "    return result\n",
    "\n",
    "# 重复执行得到错误的结果，因为result默认不会每次调用都初始化为空列表\n",
    "string = ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n",
    "print(\"string= \", string)\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2)\")\n",
    "print(find_words(string, 2))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3, ['ur'])\")\n",
    "print(find_words(string, 3, ['ur']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "string=  ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n--------------- >find_words(string, 3)< ---------------\n['dog', 'cat']\n--------------- >find_words(string, 2, ['ur'])< ---------------\n['ur', 'so', 'to']\n--------------- >find_words(string, 3)< ---------------\n['dog', 'cat']\n--------------- >find_words(string, 2)< ---------------\n['so', 'to']\n--------------- >find_words(string, 2, ['ur'])< ---------------\n['ur', 'so', 'to']\n--------------- >find_words(string, 3, ['ur'])< ---------------\n['ur', 'dog', 'cat']\n"
     ]
    }
   ],
   "source": [
    "# 使用None为占位符，None 是不可变对象，就可以正确初始化\n",
    "# 不可变对象包含：整型、浮点型、字符串、元组\n",
    "def find_words(text, wordlength, result=None):\n",
    "    if not result: result = []\n",
    "    for word in text:\n",
    "        if len(word) == wordlength:\n",
    "            result.append(word)\n",
    "    return result\n",
    "\n",
    "\n",
    "string = ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n",
    "print(\"string= \", string)\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2)\")\n",
    "print(find_words(string, 2))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3, ['ur'])\")\n",
    "print(find_words(string, 3, ['ur']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "string=  ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n--------------- >find_words(string, 3)< ---------------\n['dog', 'cat']\n--------------- >find_words(string, 2, ['ur'])< ---------------\n['ur', 'so', 'to']\n--------------- >find_words(string, 3)< ---------------\n['dog', 'cat']\n--------------- >find_words(string, 2)< ---------------\n['so', 'to']\n--------------- >find_words(string, 2, ['ur'])< ---------------\n['ur', 'so', 'to']\n--------------- >find_words(string, 3, ['ur'])< ---------------\n['ur', 'dog', 'cat']\n"
     ]
    }
   ],
   "source": [
    "# 使用与默认值不同类型的对象作为默认值也可以\n",
    "def find_words(text, wordlength, result=()):\n",
    "    if result == ():\n",
    "        result = []\n",
    "    for word in text:\n",
    "        if len(word) == wordlength:\n",
    "            result.append(word)\n",
    "    return result\n",
    "\n",
    "string = ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n",
    "print(\"string= \", string)\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2)\")\n",
    "print(find_words(string, 2))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3, ['ur'])\")\n",
    "print(find_words(string, 3, ['ur']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "string=  ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n--------------- >find_words(string, 3)< ---------------\n['dog', 'cat']\n--------------- >find_words(string, 2, ['ur'])< ---------------\n['ur', 'so', 'to']\n--------------- >find_words(string, 3)< ---------------\n['dog', 'cat']\n--------------- >find_words(string, 2)< ---------------\n['so', 'to']\n--------------- >find_words(string, 2, ['ur'])< ---------------\n['ur', 'so', 'to']\n--------------- >find_words(string, 3, ['ur'])< ---------------\n['ur', 'dog', 'cat']\n"
     ]
    }
   ],
   "source": [
    "# 使用与默认值不同类型的对象作为默认值也可以\n",
    "def find_words(text, wordlength, result=object):\n",
    "    if result is object:\n",
    "        result = []\n",
    "    for word in text:\n",
    "        if len(word) == wordlength:\n",
    "            result.append(word)\n",
    "    return result\n",
    "\n",
    "string = ['a', 'so', 'to', 'dog', 'cat', 'book', 'ship']\n",
    "print(\"string= \", string)\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3)\")\n",
    "print(find_words(string, 3))\n",
    "show_subtitle(\"find_words(string, 2)\")\n",
    "print(find_words(string, 2))\n",
    "show_subtitle(\"find_words(string, 2, ['ur'])\")\n",
    "print(find_words(string, 2, ['ur']))\n",
    "show_subtitle(\"find_words(string, 3, ['ur'])\")\n",
    "print(find_words(string, 3, ['ur']))"
   ]
  },
  {
   "source": [
    "### 4.6.4 调试技术(P173)\n",
    "使用IDE编辑工具就不用命令行调试器了"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "source": [
    "### 4.6.5 防御性编程(P174)\n",
    "测试驱动开发"
   ],
   "cell_type": "markdown",
   "metadata": {}
  }
 ]
}